//
//  UIViewController+Additions.swift
//  MGExtensionsKit
//
//  Created by Max on 2020/4/8.
//

import Foundation

public protocol AnimatedChildViewController: UIViewController {
    
    var animationViews: [UIView] { get }
    
    var backgroundViewAlpha: CGFloat { get }
    
    func dismiss(animation: ChildViewControllerAnimation, completion: (() -> ())?)
    
}

public extension AnimatedChildViewController {
    
    var animationViews: [UIView] {
        return [view]
    }
    
    var backgroundViewAlpha: CGFloat {
        return 0.5
    }
    
    func dismiss(animation: ChildViewControllerAnimation, completion: (() -> ())? = nil) {
        willMove(toParent: nil)
        animation.doDismissAnimation(for: self) {
            self.view.removeFromSuperview()
            self.removeFromParent()
            completion?()
        }
    }
}

public enum ChildViewControllerAnimation {
    /// 无
    case none
    /// 淡入淡出
    case fade
    /// 从上往下掉落
    case drop
    /// 从下往上弹出
    case cover
    /// zoom in/zoom out
    case zoom
    
    fileprivate func doShowAnimation(for viewController: AnimatedChildViewController, completion:@escaping () -> ()) {
        guard self != .none else {
            completion()
            return
        }
        viewController.view.backgroundColor = .clear
        startAnimation(for: viewController)
        UIView.animate(withDuration: 0.1, animations: {
            viewController.view.backgroundColor = UIColor.black.withAlphaComponent(viewController.backgroundViewAlpha)
        }) { _ in
            UIView.animate(withDuration: 0.1, animations: {
                self.endAnimation(for: viewController)
            }) { _ in
                completion()
            }
        }
    }
    
    fileprivate func doDismissAnimation(for viewController: AnimatedChildViewController, completion:@escaping () -> ()) {
        guard self != .none else {
            completion()
            return
        }
        UIView.animate(withDuration: 0.1, animations: {
            self.startAnimation(for: viewController)
        }) { _ in
            UIView.animate(withDuration: 0.1, animations: {
                viewController.view.backgroundColor = .clear
            }) { _ in
                completion()
            }
        }
    }
    
    fileprivate func startAnimation(for viewController: AnimatedChildViewController) {
        switch self {
        case .fade:
            viewController.animationViews.forEach({$0.alpha = 0})
        case .drop:
            viewController.animationViews.forEach({$0.transform = CGAffineTransform(translationX: 0, y: -$0.frame.maxY)})
        case .cover:
            viewController.animationViews.forEach({$0.transform = CGAffineTransform(translationX: 0, y: $0.superview!.frame.height - $0.frame.minY)})
        case .zoom:
            viewController.animationViews.forEach({$0.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)})
        default:
            break
        }
    }
    
    private func endAnimation(for viewController: AnimatedChildViewController) {
        switch self {
        case .fade:
            viewController.animationViews.forEach({$0.alpha = 1})
        case .drop, .cover, .zoom:
            viewController.animationViews.forEach({$0.transform = .identity})
        default:
            break
        }
    }
}

extension Extensive where Base: UIViewController {
    
    public func showChild(_ child: AnimatedChildViewController, animation: ChildViewControllerAnimation, completion: (() -> ())? = nil) {
        child.view.frame = base.view.bounds
        child.view.layoutIfNeeded()
        base.view.addSubview(child.view)
        base.addChild(child)
        animation.doShowAnimation(for: child) {
            child.didMove(toParent: self.base)
            completion?()
        }
    }
    
}

public extension UIViewController {
    var topController: UIViewController {
        if let present = presentedViewController {
            return present.topController
        }
        else if let tab = self as? UITabBarController {
            return tab.selectedViewController?.topController ?? tab
        }
        else if let nav = self as? UINavigationController {
            return nav.topViewController?.topController ?? nav
        }
        
        return self
    }
}

public extension UIViewController {
    func setDeviceTo(orientation: UIInterfaceOrientationMask) {
        if #available(iOS 16, *) {
            setNeedsUpdateOfSupportedInterfaceOrientations()
            
            let array = Array(UIApplication.shared.connectedScenes)
            let scene = array.first as? UIWindowScene
            let orientation = orientation
            let geometryPreferencesIOS = UIWindowScene.GeometryPreferences.iOS(interfaceOrientations: orientation)
            scene?.requestGeometryUpdate(geometryPreferencesIOS, errorHandler: { e in
                
            })
        }
        else {
            let orientationUnknown = NSNumber(integerLiteral: 0)
            UIDevice.current.setValue(orientationUnknown, forKey: "orientation")
            let orientationTarget = NSNumber(integerLiteral: orientation == .landscapeRight ? UIDeviceOrientation.landscapeRight.rawValue : UIDeviceOrientation.portrait.rawValue)
            UIDevice.current.setValue(orientationTarget, forKey: "orientation")
        }
    }
}
